package com.xwaiy.xwaiyrpc.server.tcp;

import cn.hutool.core.util.IdUtil;
import com.xwaiy.xwaiyrpc.RpcApplication;
import com.xwaiy.xwaiyrpc.exception.RpcException;
import com.xwaiy.xwaiyrpc.exception.enums.ErrorCode;
import com.xwaiy.xwaiyrpc.model.RpcRequest;
import com.xwaiy.xwaiyrpc.model.RpcResponse;
import com.xwaiy.xwaiyrpc.model.ServiceMetaInfo;
import com.xwaiy.xwaiyrpc.protocol.*;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetSocket;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * @Author Xwaiy
 * @Date 2025/8/27 17:35
 **/
public class VertxTcpClient {

    public static RpcResponse doRequest(RpcRequest request, ServiceMetaInfo metaInfo) throws InterruptedException, ExecutionException {
        Vertx vertx = Vertx.vertx();

        NetClient client = vertx.createNetClient();
        CompletableFuture<RpcResponse> resp = new CompletableFuture<>();

        client.connect(metaInfo.getServicePort(), metaInfo.getServiceHost(), result -> {
            if(!result.succeeded()) {
                System.err.println("无法连接到服务器，请检查网络连接或服务器地址");
                return;
            }

            NetSocket socket = result.result();

            ProtocolMessage<RpcRequest> reqMsg = new ProtocolMessage<>();
            ProtocolMessage.Header header = new ProtocolMessage.Header();
            header.setMagic(ProtocolConstant.PROTOCOL_MAGIC);
            header.setVersion(ProtocolConstant.PROTOCOL_VERSION);
            header.setSerializer((byte) SerializerEnum.getEnumByValue(RpcApplication.getRpcConfig().getSerializer()).getKey());
            header.setType((byte) TypeEnum.REQUEST.getKey());
            header.setRequestId(IdUtil.getSnowflakeNextId());
            reqMsg.setHeader(header);
            reqMsg.setBody(request);

            try {
                Buffer encodeBuffer = Encoder.encode(reqMsg);
                socket.write(encodeBuffer);
            } catch (IOException e) {
                throw new RpcException(ErrorCode.PROTOCOL_ENCODE_FAILED, "协议消息编码或网络写入失败", e);
            }

            TcpBufferHandler bufferHandler = new TcpBufferHandler(buffer -> {
                try{
                    ProtocolMessage<RpcResponse> respMsg = (ProtocolMessage<RpcResponse>) Decoder.decode(buffer);
                    resp.complete(respMsg.getBody());
                }catch (IOException e){
                    throw new RpcException(ErrorCode.PROTOCOL_DECODE_FAILED, "协议消息解码或网络读取失败", e);
                }
            });
            socket.handler(bufferHandler);
        });

        RpcResponse rpcResponse = resp.get();
        client.close();
        return rpcResponse;
    }

    public void start() {
        Vertx vertx = Vertx.vertx();

        vertx.createNetClient().connect(9000,"localhost",result -> {
            if (result.succeeded()) {
                System.out.println("连接TCP...");
                io.vertx.core.net.NetSocket socket = result.result();
                // 发送数据
                socket.write("weclome to coderIsland!");
                // 接收
                socket.handler(buffer -> {
                    System.out.println("接收到服务器的响应："+buffer.toString());
                });
            }else {
                System.out.println("失败");
            }
        });
    }

    public static void main(String[] args) {
        new VertxTcpClient().start();
    }
}
